package com.blog.webSocket;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.blog.bean.domain.User;
import com.blog.exception.ServiceException;
import com.blog.mapper.UserMapper;
import com.blog.webSocket.config.WebSocketConfig;
import com.blog.webSocket.domain.ChatMessage;
import com.blog.webSocket.domain.Message;
import com.alibaba.fastjson.JSONObject;
import com.blog.webSocket.service.ChatService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import javax.servlet.http.HttpSession;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * @author 任浩
 * @version 1.0
 */

@Slf4j
@ServerEndpoint(value = "/myWebSocket",configurator= WebSocketConfig.class)
@Component
@Scope("prototype")
public class WebSocketServer {
    //用来存放每个客户端对应的MyWebSocket对象。
    private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<WebSocketServer>();
    //用来记录username和该session进行绑定
    private static Map<String, Session> map = new HashMap<String, Session>();
    //与某个客户端的连接会话，需要通过它来给客户端发送数据
    private Session session;
    private String userId;
    private String username;

    private static UserMapper userMapper;

    //聊天逻辑层service
    private static ChatService chatService;

    /**
     * 初始化连接成功调用的方法。
     * @param session
     */
    @OnOpen
    public void onOpen(Session session,EndpointConfig config) {
        Map<String, List<String>> headers = (Map<String, List<String>>) config.getUserProperties().get("header");
        HttpSession httpSession = (HttpSession) config.getUserProperties().get("httpSession");
        WebApplicationContext applicationContext = WebApplicationContextUtils.getRequiredWebApplicationContext(httpSession.getServletContext());

        chatService = (ChatService) applicationContext.getBean("chatService");
        userMapper = (UserMapper) applicationContext.getBean("userMapper");

        List<String> value = headers.get("cookie");
        String val = value.get(0);
        String[] split = val.split(";");

        //遍历得到userId
        for (String s : split) {
            if (s.contains("userId")) {
                this.userId = s.split("=")[1];
            }
        }

        log.info("user_id为: {}", userId );

        this.session = session;
//        this.userId = ThreadLocalUserId.get();
//        String token = ThreadLocalToken.get();
//        log.info("token为；{}",token);

        if(userId == null || "".equals(userId)){
            log.info("用户未登录");
            throw new ServiceException("用户未登录");
        }

        webSocketSet.add(this);
        map.put(userId.toString(), session);

        log.info("webSocket连接成功");
        System.out.println("有新连接加入！当前在线连接人数为" + webSocketSet.size());
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        //断开连接，重置窗口值
//        chatService.resetWindows(username);
        webSocketSet.remove(this);  //从set中删除，当前连接人数
        map.remove(userId.toString());  //删除session

        log.info("用户 {} 断开连接", this.userId);
    }


    /**
     * 收到客户端消息后调用的方法
     * @param message 客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message) {
        try {
            //从客户端传过来的数据是json数据，所以将json数据转换为ChatMessage对象
            if (message == null || "连接成功".equals(message)){
                log.info("连接成功");
                return;
            }
            log.info("前端传递过来的数据为：{}", message);
            Message msg = JSONObject.parseObject(message, Message.class);

            //根据当前用户的id，查询出当前用户的姓名
            log.info("userId为：{}" ,this.userId);
            User user = userMapper.selectOne(new QueryWrapper<User>().eq("id", this.userId));
            username = user.getUsername();

            //根据username 查找出id。
//            User user1 = userMapper.selectOne(new QueryWrapper<User>().eq("username", msg.getReceiver()));
            User user1 = userMapper.selectOne(new QueryWrapper<User>().eq("id", Integer.parseInt(msg.getReceiver())));

            ChatMessage chatMsg = ChatMessage.builder().content(msg.getContent())
                    .type(msg.getType()) //消息的类型：分为文本和图片
                    .fromUser(this.userId) //当前用户
                    .toUser(user1.getId().toString()) //发送给消息的用户
                    .sendTime(LocalDateTime.now())
                    .isLatest(1)
                    .build();

            Session fromSession = map.get(chatMsg.getFromUser());
            Session toSession = map.get(chatMsg.getToUser());

            //发送给发送者.
            fromSession.getAsyncRemote().sendText("1" + ":" + chatMsg.getContent());

            Boolean isExists = false;
            if (toSession != null) {
                //发送给接收者.
                isExists = true;
                toSession.getAsyncRemote().sendText("-1" + ":" + chatMsg.getContent());
            }

            //判断两者是否第一次聊天，进行关系表、聊天列表、空白信息的初始化
            log.info("进行判断两者是否第一次聊天");
            chatService.isFirstChat(chatMsg.getFromUser(), chatMsg.getToUser(),isExists);

            //保存聊天记录信息
            log.info("进行保存聊天记录");
            chatService.saveMessage(chatMsg);

        }
        catch (Exception e){
            e.printStackTrace();
            log.info("发送消息失败");
            throw new ServiceException("使用webSocket，发送消息失败");
        }

        log.info("webSocket处理数据完成。");
    }

    /**
     * 发生错误时调用
     */
    @OnError
    public void onError(Session session, Throwable error) {
        error.printStackTrace();
    }
}
